home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / XPK / Source / shell / xPK.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-01  |  8.5 KB  |  398 lines

  1. #define NAME     "xPK"
  2. #define REVISION "3"
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        xPK
  7.     Author:        SDI (before 1.2 Urban Dominik Müller)
  8.     Distribution:    PD
  9.     Description:    General XPK file-to-file packer/unpacker
  10.     Compileropts:    -
  11.     Linkeropts:    -l xpkmaster
  12.  
  13.  1.0    : first public release
  14.  1.1    : docs written, version string added
  15.  1.2   19.10.96 : fixed an recursion error
  16.  1.3   29.11.96 : recompiled
  17. */
  18.  
  19. #include "SDI_defines.h"
  20. #define SDI_TO_ANSI
  21. #include "SDI_ASM_STD_protos.h"
  22. #include <pragma/exec_lib.h>
  23. #include <pragma/dos_lib.h>
  24. #include <pragma/xpkmaster_lib.h>
  25. #include <exec/memory.h>
  26.  
  27. #ifdef __MAXON__
  28.   #define __asm
  29.   #define __saveds
  30. #endif
  31.  
  32. #define lines[1000]
  33.  
  34. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *);
  35. STRPTR tempname(STRPTR);
  36. STRPTR basename(STRPTR);
  37. void   doarg(STRPTR);
  38. STRPTR dofile(STRPTR, struct FileInfoBlock *);
  39. void   end(STRPTR);
  40. LONG   isexecutable(STRPTR);
  41.  
  42. struct Hook         chunkhook    = {{0}, (ULONG (*) ()) chunkfunc};
  43. struct Library         *XpkBase    = 0;
  44. UBYTE            errbuf[300],
  45.             *err        = 0,
  46.             namebuf[200],
  47.             PrevName[100],
  48.             strbuf[200];
  49. struct FileInfoBlock     *fib        = 0;
  50.  
  51. UBYTE usage[] =
  52. "Usage: XPK [-efrsux] [-m method] [-p password] files\n"
  53. "       -e = extract files (same as -u)\n"
  54. "       -f = force packing of already packed files\n"
  55. "       -m = four letter packing method name\n"
  56. "       -p = encrypt/decrypt using password\n"
  57. "       -r = recursively (un)pack files in dir\n"
  58. "       -s = add suffix and don't delete original\n"
  59. "       -x = pack executables only\n";
  60.  
  61. UBYTE    suffix = 0, force = 0, unpack = 0, recurse = 0, depth = 0, executables = 0;
  62. STRPTR  password = 0, method = 0;
  63.  
  64. void main(int argc, char **argv)
  65. {
  66.   STRPTR c;
  67.   LONG i = 1;
  68.  
  69.   if(!(XpkBase = OpenLibrary(XPKNAME, 0)) ||
  70.   !(fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_ANY|MEMF_CLEAR)))
  71.     end("Cannot open " XPKNAME "\n");
  72.  
  73.   if(stricmp(basename(argv[0]), "XPK"))
  74.     method = basename(argv[0]);
  75.   else if(argc < 2 || !strcmp (argv[1], "?"))
  76.     end(usage);
  77.  
  78.   for(; *argv[i] == '-'; i++)
  79.     for(c = argv[i] + 1; *c; c++)
  80.     {
  81.       switch (*c)
  82.       {
  83.       case 'p': password = argv[++i]; break;
  84.       case 'm': method = argv[++i]; break;
  85.       case 's': suffix = 1; break;
  86.       case 'f': force = 1; break;
  87.       case 'e':
  88.       case 'u':    unpack = 1; break;
  89.       case 'r': recurse = 1; break;
  90.       case 'x':    executables = 1; break;
  91.       default: end(usage);
  92.       }
  93.       if(i >= argc)
  94.     end(usage);
  95.     }
  96.  
  97.   if(!method && !unpack)
  98.     end("Need a packing method, use -m\n");
  99.  
  100.   if(i == argc)
  101.     end(usage);
  102.  
  103.   for(; i < argc && !err; i++)
  104.     doarg(argv[i]);
  105.  
  106.   end(err);
  107. }
  108.  
  109. void iprint(STRPTR s)
  110. {
  111.   ULONG out = Output(), i;
  112.   for(i = depth; i; --i)
  113.     Write(out, "  ", 2);
  114.   Write(out, s, strlen(s));
  115. }
  116.  
  117. void doarg(STRPTR name)
  118. {
  119.   ULONG lock;
  120.  
  121.   if(*name == 0xFF)
  122.     return;
  123.  
  124.   if(!(lock = Lock(name, ACCESS_READ)))
  125.   {
  126.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  127.     return;
  128.   }
  129.  
  130.   if(!Examine(lock, fib))
  131.   {
  132.     UnLock(lock);
  133.     sprintf(err = errbuf, "Error %ld reading %s\n", IoErr(), name);
  134.     return;
  135.   }
  136.  
  137.   if(fib->fib_DirEntryType < 0)
  138.   {
  139.     UnLock(lock);
  140.     dofile(name, fib);
  141.   }
  142.   else if(recurse)
  143.   {
  144.     ULONG prev;
  145.  
  146.     sprintf(strbuf, "Directory %s\n", name);
  147.     iprint(strbuf);
  148.     prev = CurrentDir(lock);
  149.     *PrevName = 0xFF;
  150.  
  151.     while(ExNext(lock, fib) && !err)
  152.     {
  153.       if(SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  154.     err = " *** Break";
  155.       else
  156.       {
  157.         STRPTR thisname;
  158.     ULONG i = strlen(fib->fib_FileName) + 1;
  159.  
  160.         if(!(thisname = (STRPTR) AllocMem(i, MEMF_ANY)))
  161.         {
  162.           Write(Output(), "Not enough memory\n", 18);
  163.           break;
  164.         }
  165.     CopyMem(fib->fib_FileName, thisname, i);
  166.     depth++;
  167.     doarg(PrevName);
  168.     depth--;
  169.     strcpy(PrevName, thisname);
  170.     FreeMem(thisname, i);
  171.       }
  172.     }
  173.     depth++;
  174.     doarg(PrevName);
  175.     depth--;
  176.     *PrevName = 0xFF;
  177.  
  178.     UnLock(CurrentDir(prev));
  179.   }
  180. }
  181.  
  182. STRPTR dofile(STRPTR filename, struct FileInfoBlock *fib)
  183. {
  184.   struct XpkFib xfib;
  185.   UBYTE buf[100];
  186.   LONG len;
  187.  
  188.   if(!force || unpack)
  189.   {
  190. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  191.       struct TagItem t[] = {        /* and I don't want to use a link */
  192. #else                    /* library */
  193.       if(XpkExamineTags(&xfib,
  194. #endif
  195.     XPK_InName, (ULONG) filename,
  196.     TAG_DONE
  197. #ifdef __MAXON__
  198.       , 0 };
  199.       if(XpkExamine(&xfib, t
  200. #endif
  201.     ))
  202.     {
  203.       sprintf(buf, "Error examining %s\n", filename);
  204.       iprint(buf);
  205.       return 0;
  206.     }
  207.   }
  208.  
  209.   tempname(filename);
  210.   if(!unpack)
  211.   {
  212.     if(!force && xfib.xf_Type != XPKTYPE_UNPACKED)
  213.     {
  214.       sprintf(buf, "Skipping (already packed) %s\n", filename);
  215.       iprint(buf);
  216.       return 0;
  217.     }
  218.  
  219.     if(executables && !isexecutable(filename))
  220.       return 0;
  221.  
  222.     if(suffix)
  223.       sprintf(namebuf, "%s.xpk", filename);
  224.  
  225.     {
  226. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  227.       struct TagItem t[] = {        /* and I don't want to use a link */
  228. #else                    /* library */
  229.       if(XpkPackTags(
  230. #endif
  231.         XPK_InName, (ULONG) filename,
  232.     XPK_OutName, (ULONG) namebuf,
  233.     XPK_ChunkHook, (ULONG) &chunkhook,
  234.     XPK_GetError, (ULONG) errbuf,
  235.     XPK_PackMethod, (ULONG) method,
  236.     XPK_Password, (ULONG) password,
  237.     XPK_NoClobber, TRUE,
  238.     TAG_DONE
  239. #ifdef __MAXON__
  240.       , 0 };
  241.       if(XpkPack(t
  242. #endif
  243.       ))
  244.       {
  245.         ULONG i = strlen(errbuf);
  246.         errbuf[i] = '\n'; errbuf[i+1] = '\0';
  247.         return err = errbuf;
  248.       }
  249.     }
  250.   }
  251.   else
  252.   {
  253.     if(xfib.xf_Type != XPKTYPE_PACKED)
  254.     {
  255.       sprintf(buf, "Skipping (already unpacked) %s\n", filename);
  256.       iprint(buf);
  257.       return 0;
  258.     }
  259.  
  260.     len = strlen(filename);
  261.     suffix = 0;
  262.     if(len > 4 && !stricmp(filename + len - 5, ".xpk"))
  263.     {
  264.       strcpy(namebuf, filename);
  265.       namebuf[len - 5] = 0;
  266.       suffix = 1;
  267.     }
  268.  
  269.     {
  270. #ifdef __MAXON__            /* Maxon has no tagcall pragma now */
  271.       struct TagItem t[] = {        /* and I don't want to use a link */
  272. #else                    /* library */
  273.       if(XpkUnpackTags(
  274. #endif
  275.     XPK_InName, (ULONG) filename,
  276.     XPK_FileName, (ULONG) filename,
  277.     XPK_OutName, (ULONG) namebuf,
  278.     XPK_ChunkHook, (ULONG) &chunkhook,
  279.     XPK_Password, (ULONG) password,
  280.     XPK_GetError, (ULONG) errbuf,
  281.     XPK_NoClobber, TRUE,
  282.     TAG_DONE
  283. #ifdef __MAXON__
  284.       , 0 };
  285.       if(XpkUnpack(t
  286. #endif
  287.       ))
  288.       {
  289.         ULONG i = strlen(errbuf);
  290.         errbuf[i] = '\n'; errbuf[i+1] = '\0';
  291.         return err = errbuf;
  292.       }
  293.     }
  294.   }
  295.  
  296.   if(!suffix)
  297.   {
  298.     if(!DeleteFile(filename))
  299.       return err = "Cannot delete input file\n";
  300.     if(!Rename(namebuf, filename))
  301.       return err = "Cannot rename tempfile\n";
  302.     if(*fib->fib_Comment && !SetComment(filename, fib->fib_Comment))
  303.       return err = "Cannot set original comment\n";
  304.     if(fib->fib_Protection && !SetProtection(filename, fib->fib_Protection))
  305.       return err = "Cannot set original protection bits\n";
  306.   }
  307. }
  308.  
  309. ULONG __asm __saveds chunkfunc(register __a1 struct XpkProgress *prog)
  310. {
  311.   ULONG out = Output();
  312.   UBYTE buf[180];
  313.  
  314.   if(prog->xp_Type == XPKPROG_START)
  315.     Write(out, "\033[0 p", 5);
  316.  
  317.   if(prog->xp_Type != XPKPROG_END)
  318.     sprintf(buf,
  319.          "%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
  320.          prog->xp_PackerName, prog->xp_Activity, prog->xp_Done,
  321.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  322.   else
  323.     sprintf(buf,
  324.          "%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
  325.          prog->xp_PackerName, prog->xp_Activity, prog->xp_ULen / 1024,
  326.          prog->xp_CF, prog->xp_Speed, prog->xp_FileName);
  327.  
  328.   iprint(buf);
  329.  
  330.   if(prog->xp_Type == XPKPROG_END)
  331.     Write(out, "\033[1 p", 5);
  332.  
  333.   return SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
  334. }
  335.  
  336. STRPTR tempname(STRPTR name)
  337. {
  338.   strcpy(namebuf, name);
  339.   for(name = namebuf + strlen (namebuf); name > namebuf; name--)
  340.     if(name[-1] == '/' || name[-1] == ':')
  341.       break;
  342.   sprintf(name, "tmp%lx", &name);
  343.   return namebuf;
  344. }
  345.  
  346. LONG isexecutable(STRPTR name)
  347. {
  348.   ULONG fh;
  349.   BPTR buf[5];
  350.   UBYTE msg[100];
  351.   LONG len;
  352.  
  353.   if(!(fh = Open(name, MODE_OLDFILE)))
  354.   {
  355.     sprintf(msg, "Cannot open %s\n", name);
  356.     iprint(msg);
  357.     return 0;
  358.   }
  359.   len = Read(fh, (void *) buf, 20);
  360.   Close(fh);
  361.  
  362.   if(len < 20 || buf[0] != 0x3f3 || buf[1] != 0)
  363.   {
  364.     sprintf(msg, "%s not executable\n", name);
  365.     iprint(msg);
  366.     return 0;
  367.   }
  368.  
  369.   if(buf[3] != 0 || buf[4] + 1 != buf[2])
  370.   {
  371.     sprintf(msg, "%s overlayed\n", name);
  372.     iprint(msg);
  373.     return 0;
  374.   }
  375.   return 1;
  376. }
  377.  
  378. STRPTR basename(STRPTR name)
  379. {
  380.   STRPTR ret = name;
  381.  
  382.   for(; *name; ++name)
  383.   {
  384.     if(*name == ':' || *name == '/')
  385.       ret = name + 1;
  386.   }
  387.   return ret;
  388. }
  389.  
  390. void end(STRPTR text)
  391. {
  392.   if(text)    Write(Output(), text, strlen(text));
  393.   if(XpkBase)    CloseLibrary(XpkBase);
  394.   if(fib)    FreeMem(fib, sizeof(struct FileInfoBlock));
  395.  
  396.   exit(text ? 10 : 0);
  397. }
  398.